package com.zhy.baselibrary.base

import android.graphics.Bitmap
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.LogUtils
import com.zhy.baselibrary.api.ApiFactory
import com.zhy.baselibrary.utils.Klog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import org.json.JSONException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.text.SimpleDateFormat
import java.util.Date

open class BaseViewModel : ViewModel() {

    protected open fun <T> getApi(clz: Class<T>): T {
        return ApiFactory.factory!!.create(clz)
    }

    protected open fun <T> getApi(key: String, clz: Class<T>): T {
        return ApiFactory.factory!!.create(key, clz)
    }

    val uiModel: UIModel by lazy {
        UIModel()
    }

    var pageSize = 15

    fun <T> launch(
        block: suspend CoroutineScope.() -> BaseData<T>,
        success: (BaseData<T>) -> Unit,
        error: (String) -> Unit,
        isShowDialog: Boolean = false, //是否显示加载框
        isRefresh: Boolean = false,//是否是下拉刷新
        isError: Boolean = false,//是否将全部数据返回到界面
        isUseRefresh: Boolean = false//是否使用刷新功能
    ) {
        if (isShowDialog) {
            uiModel.showDialog.postValue(true)
        }
        viewModelScope.launch {
            flow {
                emit(block())
            }   //网络请求
                .flowOn(Dispatchers.IO)  //指定网络请求的线程
                .flowOn(Dispatchers.Main)
                .catch { t: Throwable ->
                    run {
                        handleThrow(t, error)
                        if (isShowDialog) {
                            uiModel.showDialog.postValue(false)
                        }
                    }
                }
                .collect {
                    handleData(it, success, error, isError)
                    if (isShowDialog) {
                        uiModel.showDialog.postValue(false)
                    }
                    if (isUseRefresh) {
                        //如果是下拉刷新
                        if (isRefresh) {
                            //完成刷新
                            uiModel.finishRefresh.postValue(true)
                            checkHaveMore(it)
                        } else {
                            checkHaveMore(it)
                        }
                    }
                }
        }
    }


    fun  launchBitmap(
        block: suspend CoroutineScope.() -> Bitmap,
        success: (Bitmap) -> Unit,
        error: (String) -> Unit,
    ) {
        viewModelScope.launch {
            flow {
                emit(block())
            }   //网络请求
                .flowOn(Dispatchers.IO)  //指定网络请求的线程
                .flowOn(Dispatchers.Main)
                .catch { t: Throwable ->
                    run {
                        error("网络异常, 请检查您的网络后重试${t}")
                    }
                }
                .collect {
                    success(it)
                }
        }
    }

    private fun <T> checkHaveMore(baseData: BaseData<T>) {
        val data = baseData.data
        if (data is List<*>) {
            val list = data as List<*>
            if (list.isEmpty()) {
                uiModel.finishLoadMore.postValue(false)
            } else {
                if (list.size >= pageSize) {
                    //还有更多数据
                    uiModel.finishLoadMore.postValue(true)
                } else {
                    //没有更多数据
                    uiModel.finishLoadMore.postValue(false)
                }
            }
        } else {
            uiModel.finishLoadMore.postValue(true)
        }
    }

    private fun <T> handleData(
        it: BaseData<T>,
        success: (BaseData<T>) -> Unit,
        error: (String) -> Unit,
        isError: Boolean
    ) {
        Klog.d("---------------返回数据: $it")
        success(it)
        return

    }

    /**
     * 处理网络异常
     */
    private fun handleThrow(t: Throwable, error: (String) -> Unit) {
        Klog.d("---------------异常: $t")
        t.printStackTrace()
        when (t) {
            is ConnectException -> {
                error("网络异常, 请检查您的网络后重试")
            }

            is SocketTimeoutException -> {
                error("连接超时")
            }

            is JSONException -> {
                error("数据异常")
            }

            else -> {
                error("服务器异常")
            }
        }
    }

    inner class UIModel {
        val showProgress by lazy { MutableLiveData<String>() }    //显示加载框
        val showDialog by lazy { MutableLiveData<Boolean>() }    //显示加载框
        val finishRefresh by lazy { MutableLiveData<Boolean>() } //是否是刷新状态
        val finishLoadMore by lazy { MutableLiveData<Boolean>() } //是否是加载状态 false没有更多数据
    }
}